<?php

namespace App\Kuafu\Product\Controller\Merchant;

use App\Exceptions\BaseException;
use App\Exceptions\CustomValidateException;
use App\Kuafu\Base\Controller\BaseController;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Enum\ClientEnum;
use App\Kuafu\Base\Enum\DBEnum;
use App\Kuafu\Category\Service\CategoryService;
use App\Kuafu\Category\Service\MerchantCategoryService;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Config\Model\ConfigModel;
use App\Kuafu\Export\Model\ExportDownloadModel;
use App\Kuafu\Export\Service\ExportDownloadService;
use App\Kuafu\Order\Enum\OrderCodeEnum;
use App\Kuafu\Order\Enum\OrderMerchantEnum;
use App\Kuafu\Order\Exceptions\OrderException;
use App\Kuafu\Order\Service\OrderMerchantUseService;
use App\Kuafu\Product\Enum\CodeEnum;
use App\Kuafu\Product\Enum\ProductCodeEnum;
use App\Kuafu\Product\Exceptions\ProductException;
use App\Kuafu\Product\Service\MerchantProductService;
use App\Kuafu\Product\Service\ProductService;
use App\Kuafu\Product\Validate\ProductNewValidate;
use App\Kuafu\Product\Validate\ProductValidate;
use App\Kuafu\ProductMenu\Enum\ProductMenuCodeEnum;
use App\Kuafu\ProductMenu\Exceptions\ProductMenuException;
use App\Kuafu\ProductMenu\Model\ProductMenu;
use App\Kuafu\ProductMenu\Service\ProductMenuService;
use App\Kuafu\Shop\Exceptions\ShopException;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\User\Exceptions\UserException;
use App\Kuafu\User\Service\AuthService;
use App\Kuafu\WaiMai\Channel\BaseWaiMai;
use App\Kuafu\WaiMai\Service\BaseWaiMaiOrderService;
use App\Kuafu\WaiMai\Service\WaiMaiProductService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use PHP_CodeSniffer\Reports\Code;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class ProductController extends BaseController
{
    /**
     * 店铺下的菜品列表
     * @param Request $request
     * @return JsonResponse
     * @throws OrderException
     * @throws ShopException
     * @throws \App\Kuafu\WaiMai\Exceptions\WaiMaiException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function shopProducts(Request $request)
    {
        $shopId    = (int)$this->shopId;
        $orderType = (int)$request->get('orderType', OrderMerchantEnum::ORDER_TYPE_IN);

        $lists = MerchantProductService::getShopProductsByOrderType($orderType, $shopId);

        return $this->success(['lists' => $lists]);
    }

    /**
     * 店铺下的分类列表
     * @param Request $request
     * @return JsonResponse
     * @throws OrderException
     * @throws ShopException
     */
    public function shopCategories(Request $request)
    {
        $shopId    = (int)$this->shopId;
        $brandId   = (int)$this->brandId;
        $orderType = (int)$request->get('orderType', OrderMerchantEnum::ORDER_TYPE_IN);

        $lists = MerchantCategoryService::getShopCategoriesByOrderType($orderType, $shopId, $brandId);

        return $this->success(['lists' => $lists]);
    }

    /**
     * 堂食 - 菜品销售统计
     * @param Request $request
     * @return JsonResponse
     * @throws OrderException
     * @throws ProductException
     */
    public function inOrderStatistics(Request $request)
    {
        $showTimeTab   = (int)$request->get('showTimeTab', OrderMerchantEnum::SHOW_TIME_TAB_TODAY);
        $showStartAt   = (int)$request->get('showStartAt', 0);
        $showEndAt     = (int)$request->get('showEndAt', 0);
        $groupByType   = (int)$request->get('groupByType',
            OrderMerchantEnum::PRODUCT_SALES_GROUP_BY_PRODUCT); // 1按菜品分组 2分类分组
        $filterIds     = $request->get('filterIds', []) ?: []; // 筛选的Ids 菜品/分类
        $orderByColumn = (int)$request->get('orderByColumn',
            OrderMerchantEnum::PRODUCT_SALES_COLUMN_SALES_NUM); // 排序字段 销量占比、实收占比
        $sort          = (string)strtolower($request->get('sort', 'desc')); // 顺序、倒序

        $data = (new OrderMerchantUseService([$this->shopId]))
            ->setShowTimeTab($showTimeTab, $showStartAt, $showEndAt)
            ->inOrderProductStatisticsUse($filterIds, $groupByType, $orderByColumn, $sort);

        return $this->success($data);
    }


    public function waiMaiOrderStatistics(Request $request)
    {
        $showTimeTab = (int)$request->get('showTimeTab', OrderMerchantEnum::SHOW_TIME_TAB_TODAY);
        $showStartAt = (int)$request->get('showStartAt', 0);
        $showEndAt   = (int)$request->get('showEndAt', 0);
//        $groupByType   = (int)$request->get('groupByType', OrderMerchantEnum::PRODUCT_SALES_GROUP_BY_PRODUCT); // 1按菜品分组 2分类分组
        $filterNames   = $request->get('filterNames', []) ?: []; // 筛选的菜品名称
        $orderByColumn = (int)$request->get('orderByColumn',
            OrderMerchantEnum::PRODUCT_SALES_COLUMN_SALES_NUM); // 排序字段 销量占比、实收占比
        $sort          = (string)strtolower($request->get('sort', 'desc')); // 顺序、倒序
        $sourceType    = (int)$request->get('sourceType', 0);

        $data = (new OrderMerchantUseService([$this->shopId]))
            ->setShowTimeTab($showTimeTab, $showStartAt, $showEndAt)
            ->waiMaiOrderProductStatisticsUse($filterNames, OrderMerchantEnum::PRODUCT_SALES_GROUP_BY_PRODUCT,
                $orderByColumn, $sort, $sourceType);

        return $this->success($data);
    }


    /**
     * 店铺下的菜单、菜品、分类列表
     *
     * @param Request $request
     * @return JsonResponse
     * @throws ShopException
     */
    public function lists(Request $request): JsonResponse
    {
        $updatedAt = $request->get('updatedAt', 0);

        // 店铺的菜单信息
        $shop   = ShopService::getShopInfo($this->shopId);
        $menuId = $shop->menuId ?? 0;
        if (!$menuId) {
            return $this->fail(ProductCodeEnum::ERR_PRODUCT_NO_MENU);
        }
        $menu = ProductMenu::query()->select('id', 'name', 'desc', 'createdAt', 'updatedAt')->find($menuId);
        if (!$menu || $menu->status != DBEnum::STATUS_ON) {
            return $this->fail(
                ProductMenuCodeEnum::ERR_FOOD_MENUS_NULL_OFFLINE,
                ProductMenuCodeEnum::getCodeText(ProductMenuCodeEnum::ERR_FOOD_MENUS_NULL_OFFLINE)
            );
        }
        $menu              = $menu->toArray();
        $menu['createdAt'] = strtotime($menu['createdAt']);
        $menu['updatedAt'] = strtotime($menu['updatedAt']);
        $data['menu']      = $menu;
        // 有新变动才返回数据
        if ($updatedAt < $menu['updatedAt']) {
            // 菜品列表-获取所有
            $oriList = ProductMenuService::shopProductLists(ClientEnum::QUERY_CLIENT_TYPE_ALL,
                DBEnum::QUERY_STATUS_ALL);

            // 分类信息
            $productList  = [];
            $field        = ['id', 'name', 'sort'];
            $data         = CategoryService::filterNoProductCategory($this->brandId, $menuId, $field, $oriList,
                $productList, 1);
            $productList  = $data['productList'];
            $categoryList = $data['categoryList'];
        }
        $data = [
            'menu'         => $menu,
            'productList'  => $productList ?? null,
            'categoryList' => $categoryList ?? null,
        ];
        return $this->success($data);
    }

    /**
     * 修改店铺菜品的自定义状态
     *
     * @param Request $request
     * @return JsonResponse
     * @throws ProductMenuException
     * @throws ProductException
     */
    public function doStatus(Request $request): JsonResponse
    {
        $productId = $request->post('productId');
        $status    = $request->post('status');
        $out       = $request->post('out', 0);
        $valid     = ProductValidate::doStatus($request);
        if ($valid) {
            return $this->fail(ProductCodeEnum::ERR_PRODUCT_NOT_INPUT, $valid);
        }
        ShopService::doProductStatus($productId, $status, $out);
        return $this->success(['productId' => $productId]);
    }


//    /**
//     * 添加菜品
//     *
//     * @param Request $request
//     * @return JsonResponse
//     * @throws ProductException
//     */
//    public function addProduct(Request $request): JsonResponse
//    {
//        //merchant端添加商品 固定为自定义类型和商品分类
//        $request->merge([
//            "kind"       => CodeEnum::KIND_CUSTOMER,
//            "categoryId" => ConfigModel::query()
//                                       ->where("key", "customProductCategoryId")
//                                       ->where("type", "merchant")
//                                       ->pluck("value")->first()
//        ]);
//        $type = $request->type ?: 0;
//        //参数校验
//        $valid = ProductValidate::addProduct($request);
//        if ($valid) {
//            return $this->fail(ProductCodeEnum::ERR_PRODUCT_INSERT, $valid);
//        }
//        if ($request->type == CodeEnum::PRODUCT_TYPE_PACKAGE) {
//            //检验套餐数据
//            $valid = ProductValidate::checkPackageData($request);
//            if ($valid) {
//                return $this->fail(ProductCodeEnum::ERR_PRODUCT_INSERT, $valid);
//            }
//            ProductService::checkPackageTotalPrice($request->productList, $request->price, $request->vipPrice);
//        }
//        ProductService::addProduct($request, $type);
//        return $this->success();
//    }

    /**
     * 修改菜品基本信息
     * @param Request $request
     * @return JsonResponse
     * @throws ProductException
     * @throws UserException
     */
    public function setProductById(Request $request): JsonResponse
    {
        $type = $request->type ?: 0;
        if (empty($request->productId)) {
            return $this->fail(BaseCodeEnum::ERR_400009, '非法数据,参数错误');
        }
        $valid = ProductValidate::addProduct($request);
        if ($valid) {
            return $this->fail(ProductCodeEnum::ERR_PRODUCT_INSERT, $valid);
        }
        if ($type == CodeEnum::PRODUCT_TYPE_PACKAGE) {
            //检验套餐数据
            $valid = ProductValidate::checkPackageData($request);
            if ($valid) {
                return $this->fail(ProductCodeEnum::ERR_PRODUCT_INSERT, $valid);
            }
            ProductService::checkPackageTotalPrice($request->productList, $request->price, $request->vipPrice);
        }
        ProductService::setProductById($request, $type);
        return $this->success();
    }


    /**
     * 根据id获取产品详情
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function getProductInfoById(Request $request): JsonResponse
    {
        if (empty($request->productId)) {
            return $this->fail(BaseCodeEnum::ERR_400009, '非法数据,参数错误');
        }
        $productInfoById = ProductService::getProductInfoById($request->productId);
        $return          = null;
        if ($productInfoById) {
            $return              = $productInfoById;
            $return['price']     = $return['price'] ?: '';
            $return['vipPrice']  = $return['vipPrice'] ?: '';
            $return['costPrice'] = $return['costPrice'] ?: '';
            $return['imageUrl']  = CommonService::joinImageUrl($return['imageUrl']);
        }
        return $this->success($return);
    }


    /**
     * 获取菜品列表
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function getProductList(Request $request): JsonResponse
    {
        $name       = (string)$request->get('name', '');
        $categoryId = (int)$request->get('categoryId', 0);
        $pageSize   = (int)$request->get('pageSize', 20);
        $pageNum    = (int)$request->get('pageNum', 1);
        $brandId    = $request->header('brandId');
        $menuId     = 0;
        return $this->success(ProductService::getProductList($brandId, $categoryId, $name, $pageSize, $pageNum,
            $menuId));
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ProductException
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|CustomValidateException
     */
    public function insert(Request $request): JsonResponse
    {
        $brandId = $request->header('brandId', 0);
        $shopId  = $request->header('shopId', 0);
        ProductService::insert(
            $shopId,
            $brandId,
            ProductNewValidate::merchantInsertValidate(
                $request->merge([
                    "type" => CodeEnum::PRODUCT_TYPE_PACKAGE,
                ])->all()
            )
        );
        return $this->success();
    }

    /**
     * 编辑菜品
     *
     * @param Request $request
     * @param int $productId
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws ValidationException
     */
    public function update(Request $request, int $productId): JsonResponse
    {
        $brandId = $request->header('brandId', 0);
        $shopId  = $request->header('shopId', 0);
        ProductService::update(
            $shopId,
            $brandId,
            ProductNewValidate::merchantUpdateValidate($productId, $request->all())
        );
        return $this->success();
    }

    /**
     * 菜品详情
     *
     * @param Request $request
     * @param int $productId
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws ValidationException
     */
    public function detail(Request $request, int $productId): JsonResponse
    {
        $brandId = $request->header('brandId', 0);
        $shopId  = $request->header('shopId', 0);
        ProductNewValidate::detailValidate($request->merge(["id" => $productId])->all());
        return $this->success(ProductService::detail($productId, $shopId, $brandId));
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ProductException
     */
    public function ordinaryProducts(Request $request): JsonResponse
    {
        $shopId  = $request->header("shopId", 0);
        $brandId = $request->header('brandId', 0);
        return $this->success(ProductService::ordinaryProducts($shopId, $brandId));
    }

    /**
     * 修改菜品状态
     *
     * @param Request $request
     * @param int $productId
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws ProductMenuException
     * @throws ShopException
     * @throws ValidationException
     * @throws BaseException
     */
    public function status(Request $request, int $productId): JsonResponse
    {
        $shopId  = $request->header("shopId", 0);
        $brandId = $request->header("brandId", 0);
        $params  = ProductNewValidate::merchantStatusValidate($request->merge(["id" => $productId])->all());
        ProductService::merchantStatus($shopId, $brandId, $params);
        return $this->success();
    }

    /**
     * @param Request $request
     * @param int $productId
     * @return JsonResponse
     * @throws BaseException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ProductException
     * @throws UserException
     * @throws ValidationException
     */
    public function delete(Request $request, int $productId): JsonResponse
    {
        $shopId  = $request->header("shopId", 0);
        $brandId = $request->header("brandId", 0);

        $params = ProductNewValidate::merchantDeleteValidate($request->merge(["id" => $productId])->all());
        ProductService::delete($shopId, $brandId, $params);
        return $this->success();
    }

    /**
     * @throws ValidationException
     */
    public function priceTagGenerate(Request $request)
    {
        $this->validate($request, [
            'goods' => 'required|array'
        ]);

        $user    = AuthService::getAuthUser();
        $shopId  = $request->header("shopId", 0);
        $brandId = $request->header("brandId", 0);
        $goods   = $request->post('goods', []);

        if (count($goods) > 100) {
            return $this->fail(400, '限制价签生成数量必须小于100个');
        }

        $params = [
            'user'    => $user,
            'shopId'  => $shopId,
            'brandId' => $brandId,
            'goods'   => $goods,
            'fileName' => '商品价格签下载-' . Carbon::now()->format('Y-m-d_H:i:s')
        ];

        ExportDownloadService::export(ExportDownloadModel::CLIENT_TYPE_APP,
            ExportDownloadModel::FILE_TYPE_APP_SHOP_PRICE_TAG_LIST, $shopId,
            OrderMerchantEnum::SHOW_TIME_TAB_DEFINE, strtotime('-1 day'), time(), [], $params,
        );

        return $this->success();
    }
}
